package com.loong.tool.secret.base;

import com.loong.tool.secret.exception.InvalidCodeException;

/**
 * Hex处理类
 * 
 * @author 张成轩
 */
public class Hex {

	private static final char DIGITS[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e',
			'f' };

	private static final byte INT[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
			-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14,
			15 };

	/**
	 * Hex加码
	 * 
	 * @param bytes 待处理字节数组
	 * @return Hex字符串
	 */
	public static String encode(byte[] bytes) {

		int l = bytes.length;
		StringBuilder result = new StringBuilder(l << 1);
		for (int i = 0; i < l; i++) {
			result.append(DIGITS[(0xF0 & bytes[i]) >>> 4]);
			result.append(DIGITS[0x0F & bytes[i]]);
		}
		return result.toString();
	}

	/**
	 * Hex解码
	 * 
	 * @param str 待解码Hex字符串
	 * @return 字节数组
	 */
	public static byte[] decode(String str) {

		int l = str.length();
		int group = l / 2;
		if (2 * group != l)
			throw new InvalidCodeException("error code length");
		byte[] result = new byte[group];
		int inCursor = 0, outCursor = 0;
		for (int i = 0; i < group; i++) {
			int ch0 = toInt(str.charAt(inCursor++), INT);
			int ch1 = toInt(str.charAt(inCursor++), INT);
			result[outCursor++] = (byte) (ch0 << 4 | ch1);
		}
		return result;
	}

	private static int toInt(char c, byte[] alphaToInt) throws InvalidCodeException {

		int result = alphaToInt[c];
		if (result < 0)
			throw new InvalidCodeException("code error: " + c);
		return result;
	}
}
